home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / GRAPHICS / RAYTRACE.ZIP / HT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-27  |  21.8 KB  |  728 lines

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <malloc.h>
  4. #include <mem.h>
  5. #include <string.h>
  6. #include <dos.h>
  7. #include <time.h>
  8. #include <io.h>
  9. #include <fcntl.h>
  10. #include <sys\stat.h>
  11. #include <math.h>
  12. #include "loadpcx.h"
  13.  
  14. typedef unsigned long   ULONG;
  15. typedef unsigned short  UINT;
  16. typedef unsigned char   UCHAR;
  17.  
  18. #define USE_ASSEMBLER   1   // Set to 0 to use C routines
  19.  
  20. #define MAX_ANGLE       1280
  21. #define COLUMN_AMOUNT   2
  22. #define HALF_SCREEN     (320/COLUMN_AMOUNT)
  23.  
  24. #define M_PI        3.14159265358979323846
  25. #define RAYLENGTH           160
  26. #define MAXLENGTH           220
  27. #define WORLDX              320
  28. #define WORLDY              200
  29. #define WORLDSIZE           65535
  30.  
  31. // The altitude of the viewer. (Above ground)
  32. #define USERALT             32
  33.  
  34. // How far to look out over the horizon, the large the value the slower it is
  35. #define HORIZON_DISTANCE    90
  36.  
  37. // How fast the viewer moves, the larger the value, the faster but also the
  38. // more choppier the screen will be.
  39. #define VIEWER_SPEED        3
  40.  
  41.  
  42. #define ABS(a)   ((a < 0) ? -a : a)
  43. #define SGN(a)   ((a < 0) ? -1 : 1)
  44.  
  45.  
  46. #define KEYBD               0x9     // Keyboard interrupt
  47. #define RIGHT_ARROW_KEY     77
  48. #define UP_ARROW_KEY        72
  49. #define LEFT_ARROW_KEY      75
  50. #define DOWN_ARROW_KEY      80
  51. #define MINUS_KEY           74
  52. #define PLUS_KEY            78
  53. #define NUMBER_5_KEY        76
  54. #define ESCAPE_KEY          1
  55. #define PGUP_KEY            73
  56. #define PGDN_KEY            81
  57. #define B_KEY               48
  58. #define C_KEY               46
  59. #define F_KEY               33
  60. #define I_KEY               23
  61. #define R_KEY               19
  62. #define S_KEY               31
  63. #define W_KEY               17
  64. #define NUM_1_KEY           2
  65. #define NUM_2_KEY           3
  66. #define NUM_3_KEY           4
  67. #define NUM_4_KEY           5
  68. #define NUM_5_KEY           6
  69. #define NUM_6_KEY           7
  70. #define NUM_7_KEY           8
  71. #define NUM_8_KEY           9
  72. #define NUM_9_KEY           10
  73.  
  74.     UCHAR   scanCode;
  75.     UCHAR   KeyPressed;
  76.     UCHAR   MiniKey;
  77.     UCHAR   Keys[128];
  78.  
  79.     short   TopRow;
  80.     short   HorizonTilt;
  81.     short   CurrentAlt;
  82.     UCHAR   *Video;
  83.     UCHAR   *Buffer;
  84.     UCHAR   *World;
  85.     UCHAR   *Color;
  86.     UCHAR   *Sky;
  87.     UCHAR   *BackDrop;
  88.     short   USERX;
  89.     short   USERY;
  90.     short   USERA;
  91.     short   xPosns[MAX_ANGLE];
  92.     short   yPosns[MAX_ANGLE];
  93.     long    sine[MAX_ANGLE];
  94.     long    cosine[MAX_ANGLE];
  95.     short   startpostable[MAXLENGTH+50];
  96.     short   startposOrg[MAXLENGTH+50];
  97.     unsigned short OffsetTable[200];
  98.     long    RangeTable[HORIZON_DISTANCE * 2];
  99.  
  100.     short   RowTable[200];
  101.     short   ColorTable[200];
  102.     short   UserAlt;
  103.     UCHAR   Used[200];
  104.     struct  VgaPalette PalBuf[256];
  105.  
  106.     void    (__interrupt __far *oldvec)();
  107.     void    __interrupt __far myInt();
  108.  
  109. #if USE_ASSEMBLER
  110.     void    CopyVertical(void);
  111.     void    FillLinearBuffer(short startpos,short length);
  112.     void    FillUsedBuffer(void);
  113. #endif
  114.  
  115. extern  UCHAR   colordat[];
  116.  
  117.  
  118. //=============================================================================
  119. // Keyboard interrupt 9
  120. //=============================================================================
  121. void __interrupt __far myInt(void)
  122. {
  123.   register char x;
  124.  
  125. // oldvec();    // Use when screen captures are wanted - calls orig vector
  126.  
  127. scanCode = inp(0x60); // read keyboard data port
  128. x = inp(0x61);
  129. outp(0x61, (x | 0x80));
  130. outp(0x61, x);
  131. outp(0x20, 0x20);
  132.  
  133. Keys[scanCode & 127] = 1;
  134. KeyPressed = 1;
  135. if (scanCode & 128)
  136.     {
  137.     Keys[scanCode & 127] = 0;
  138.     KeyPressed = 0;
  139.     }
  140. else
  141.     MiniKey = 1;
  142.  
  143. }
  144.  
  145. //=============================================================================
  146. // Sets the 256 color palette. pBuf contains the RGB values to set
  147. //=============================================================================
  148. void SetPalette(UCHAR *pbuf)
  149. {
  150.     short     cnt,index;
  151.  
  152. cnt = 256;
  153. index = 0;
  154.  
  155. while (cnt-- > 0)
  156.     {
  157.     outp(0x3c8,index++);
  158.     outp(0x3c9,*pbuf++);
  159.     outp(0x3c9,*pbuf++);
  160.     outp(0x3c9,*pbuf++);
  161.     }
  162.  
  163. }
  164.  
  165. //=============================================================================
  166. //
  167. //=============================================================================
  168. void SetVideoMode(short Mode)
  169. {
  170.     union REGPACK regs;
  171.  
  172. memset(®s,0,sizeof(union REGPACK));  // Make sure segments are zero
  173. regs.w.ax = Mode;                       // Set the mode we want to go to
  174. intr(0x10,®s);                       // Use INT 10h to set mode
  175.  
  176. }
  177.  
  178. //=============================================================================
  179. //
  180. //=============================================================================
  181. short LoadFiles(void)
  182. {
  183.     FILE    *Data;
  184.     UCHAR   *bPtr;
  185.     struct  PcxPix  PcxBuf;
  186.  
  187. if (load_pcx("ht.pcx",&PcxBuf,PalBuf) != pcx_ok)
  188.     return(1);
  189.  
  190. BackDrop = PcxBuf.image;
  191.  
  192. if (load_pcx("sky.pcx",&PcxBuf,PalBuf) != pcx_ok)
  193.     return(2);
  194.  
  195. Sky = PcxBuf.image;
  196.  
  197. if (load_pcx("Altitude.pcx",&PcxBuf,PalBuf) != pcx_ok)
  198.     return(3);
  199.  
  200. bPtr = PcxBuf.image;
  201.  
  202. World = malloc(65536);                  // Get a buffer for entire area
  203. if (World == NULL)
  204.     return(3);
  205.  
  206. memmove(World,bPtr,64000);
  207. memmove(&World[64000],bPtr,1536);   // Then duplicate some rows
  208. free(bPtr);
  209.  
  210.  
  211. if (load_pcx("Color.pcx",&PcxBuf,PalBuf) != pcx_ok)
  212.     return(4);
  213.  
  214. bPtr = PcxBuf.image;
  215.  
  216. Color = malloc(65536);                  // Get a buffer for the entire area
  217.  
  218. if (Color == NULL)
  219.     return(4);
  220.  
  221. memmove(Color,bPtr,64000);
  222. memmove(&Color[64000],bPtr,1536);      // Then duplicate some rows
  223. free(bPtr);
  224.  
  225. return(0);
  226. }
  227.  
  228. //=============================================================================
  229. // Calculate a circular area around the center origin that will be the
  230. // coordinates for our viewing area. These coordinates will then be added to
  231. // the viewers current X,Y coordinates to give us the endpoints of the line
  232. // we will cast.
  233. //=============================================================================
  234. void SetViewDistance(void)
  235. {
  236.     short   Angle;
  237.  
  238. for (Angle = 0; Angle < MAX_ANGLE; Angle++)
  239.     {
  240.     xPosns[Angle] = (cosine[Angle] * HORIZON_DISTANCE) >> 14;
  241.     yPosns[Angle] = (sine[Angle] * HORIZON_DISTANCE) >> 14;
  242.     }
  243.  
  244.  
  245. }
  246.  
  247. //=============================================================================
  248. // Setup our two arrays for quicker sine and cosine calculations.
  249. //=============================================================================
  250. void InitSinCos(void)
  251. {
  252.     int     a;
  253.     float   A;
  254.  
  255. for (a = 0;a < MAX_ANGLE;a++)
  256.     {
  257.     A = a;                                  // Get angle in a float
  258.     A = (A * M_PI) / (MAX_ANGLE/2);         // Convert degrees to radians
  259.     sine[a] = sin(A) * 16384;               // Get fixed point sine 2^14
  260.     cosine[a] = cos(A) * 16384;             // Get fixed point cosine 2^14
  261.     }
  262.  
  263. SetViewDistance();
  264.  
  265. }
  266.  
  267. //=============================================================================
  268. //
  269. //=============================================================================
  270. void InitStartPosTable(void)
  271. {
  272.     int     i,distance;
  273.     long    ht;
  274.  
  275. ht = (long)16 << 14;                            // Set fixed point height
  276.  
  277. for (distance = 1; distance < (HORIZON_DISTANCE*2); distance++)
  278.     {
  279.     RangeTable[distance] = ht / distance;   // Setup height range table
  280.     }
  281.  
  282. for (i = 1;i < (RAYLENGTH+50);i++)
  283.     {
  284.     startposOrg[i] = startpostable[i] = 500 / i;    // Used for rows on screen
  285.     startpostable[i] += HorizonTilt;
  286.     }
  287.  
  288. for (i = 0; i < 200; i++)
  289.     OffsetTable[i] = i * 320;               // Faster video offset lookups
  290.  
  291. }
  292.  
  293.     long    OldPos;
  294.     long    HighRow;
  295.     long    CurrentColumn;
  296.     long    CurrentAngle;
  297.     UCHAR   CurrentColor;
  298.  
  299. //=============================================================================
  300. //
  301. //=============================================================================
  302. void DrawLine(void)
  303. {
  304.     short           i,x1,y1,x2,y2;
  305.     short           length,startpos;
  306.     long            height;
  307.     short           d,ax,ay,sx,sy,dx,dy,yOff;
  308.     short           BegRow,NumRows;
  309.     unsigned short  offset;
  310.     unsigned char   c;
  311.     short           *sptPtr;
  312.     UCHAR           *bPtr;
  313.  
  314.  
  315. OldPos = 199;                       // Used to speed up drawing
  316. HighRow = 200;                      // Marker of highest row drawn to
  317.  
  318. offset = OffsetTable[USERY] + USERX; // Current location in color map
  319. CurrentColor = Color[offset];        // Current color at viewer location
  320.  
  321. #if USE_ASSEMBLER
  322.     FillUsedBuffer();
  323. #else
  324.     memset(&Used[100],CurrentColor,100);  // Pre-fill buffer to cover holes????
  325. #endif
  326.  
  327. x1 = USERX + xPosns[CurrentAngle];  // Get our most distance coordinates
  328. y1 = USERY + yPosns[CurrentAngle];
  329. x2 = USERX;                         // Put viewer coordinates into temps
  330. y2 = USERY;
  331.  
  332. offset = y1 * WORLDX + x1;          // Calculate offset into buffers
  333. dx = x2-x1;                         // Get our delta X
  334. ax = abs(dx) << 1;                  // Get our delta X * 2 for difference checks
  335. sx = SGN(dx);                       // Get 1 or -1 based on sign of delta X
  336. dy = y2-y1;                         // Get our delta Y
  337. ay = abs(dy) << 1;                  // Delta Y * 2 for difference checks
  338. sy = SGN(dy);                       // Get 1 or -1 based on sign of delta Y
  339. yOff = WORLDX;                      // Assume a positive sign and get offset
  340. if (sy < 0)                         // If negative direction then
  341.     yOff = -WORLDX;                 // use a minus offset (this is a row offset)
  342.  
  343. if (ax > ay)                        // Is our X difference greater than Y diff?
  344.     {
  345.     d = ay - (ax >> 1);             // Yes, calc the error term to use
  346.     length = abs(dx);                   // Length of the line to plot
  347.     sptPtr = &startpostable[length];    // Use pointer to avoid indexing
  348.     for (i = length; i > 0; i--)
  349.         {
  350.         CurrentColor = Color[offset];   // Color to use for this segment of column
  351.         // Height is calculated by taking the height of the current location
  352.         // subtracting the viewer height, then multiplying by the pre-calc'd
  353.         // distance perspective table divided by the current length of the
  354.         // line. See how RangeTable is setup for further details. The table is
  355.         // used so a faster multiply can be done vs a slower divide by length
  356.         // for each unit of the line.
  357.         height = ((World[offset] - UserAlt) * RangeTable[i]) >> 14;
  358.  
  359.         // Perspective transform takes a predetermined height for the length
  360.         // of the line and subtracts the calculated height above. This gives
  361.         // us an actual height for the location we are currently examining.
  362.         // Note below that startpos is actual a delta height greater than
  363.         // the last height we calculated. OldPos is used to remember the last
  364.         // height we found.
  365.         startpos = *sptPtr - height;
  366.         sptPtr--;
  367.  
  368.     #if USE_ASSEMBLER
  369.         FillLinearBuffer(startpos,i);
  370.     #else
  371.         if (startpos > OldPos)          // Are we beyond the last height?
  372.             {
  373.             // Are we in bounds for the screen vertical height?
  374.             if (startpos > 0 && startpos < 200 && OldPos < 200)
  375.                 {
  376.                 if (i < 10)             // Check our length and fill from
  377.                     {                   // the bottom up
  378.                     NumRows = 200 - OldPos;  // for the last height remembered.
  379.                     BegRow = 199;
  380.                     }
  381.                 else
  382.                     {
  383.                     // Otherwise start with current minus last as number of rows
  384.                     NumRows = startpos - OldPos;
  385.                     BegRow = startpos;
  386.                     }
  387.  
  388.                 BegRow -= NumRows;      // We want to build downward not up.
  389.                 if (BegRow < 0)         // If starting row went negative
  390.                     {
  391.                     NumRows += BegRow;  // Adjust the number of rows
  392.                     BegRow = 0;         // And start at top of column
  393.                     }
  394.  
  395.                 if (BegRow < HighRow)   // Keep our high water mark updated
  396.                     HighRow = BegRow;
  397.  
  398.  
  399.                 // Copy the color into a buffer which will later be used
  400.                 // to display the vertical column.
  401.                 memset(&Used[BegRow],CurrentColor,NumRows);
  402.                 }
  403.             }
  404.     #endif
  405.  
  406.         OldPos = startpos;          // Now update our remembered height
  407.  
  408.         if( d >= 0 )                // Check error term to see if Y coordinate
  409.             {                       // needs to be adjusted
  410.             offset += yOff;         // Bump buffer offset to next row
  411.             d -= ax;                // and reset our error term
  412.             }
  413.  
  414.         offset += sx;               // Bump buffer offset to next column
  415.         d += ay;                    // and adjust our error term
  416.         }
  417.     }
  418. else        // Here if the Y difference is >= the X difference
  419.     {
  420.     d = ax - (ay >> 1);
  421.     length = abs(dy);
  422.     sptPtr = &startpostable[length];    // Use pointer to avoid indexing
  423.     for (i = length; i > 0; i--)
  424.         {
  425.         CurrentColor = Color[offset];
  426.         height = ((World[offset] - UserAlt) * RangeTable[i]) >> 14;
  427.  
  428.         // Perspective transform
  429.         startpos = *sptPtr - height; // Get perspective height for this distance
  430.         sptPtr--;
  431.  
  432.     #if USE_ASSEMBLER
  433.         FillLinearBuffer(startpos,i);
  434.     #else
  435.         if (startpos > OldPos)
  436.             {
  437.             if (startpos > 0 && startpos < 200 && OldPos < 200)
  438.                 {
  439.                 if (i < 10)
  440.                     {
  441.                     NumRows = 200 - OldPos;
  442.                     BegRow = 199;
  443.                     }
  444.                 else
  445.                     {
  446.                     NumRows = startpos - OldPos;
  447.                     BegRow = startpos;
  448.                     }
  449.  
  450.                 BegRow -= NumRows;
  451.                 if (BegRow < 0)
  452.                     {
  453.                     NumRows += BegRow;
  454.                     BegRow = 0;
  455.                     }
  456.                 if (BegRow < HighRow)
  457.                     HighRow = BegRow;
  458.                 memset(&Used[BegRow],CurrentColor,NumRows);
  459.                 }
  460.             }
  461.     #endif
  462.  
  463.  
  464.         OldPos = startpos;          // Used to speed up rendering.
  465.  
  466.         if( d >= 0 )
  467.             {
  468.             offset += sx;
  469.             d -= ay;
  470.             }
  471.         offset += yOff;
  472.         d += ax;
  473.         }
  474.     }
  475.  
  476. // Now copy our buffer to the vertical column of the screen
  477.  
  478. #if USE_ASSEMBLER
  479.     CopyVertical();
  480. #else
  481.     bPtr = Buffer + OffsetTable[HighRow] + CurrentColumn;
  482.     for (i = HighRow; i < 200; i++)
  483.         {
  484.         c = Used[i];
  485.         *bPtr = c;
  486.         bPtr[1] = c;
  487.         bPtr += 320;
  488.         }
  489. #endif
  490.  
  491. }
  492.  
  493.  
  494. //=============================================================================
  495. //
  496. //=============================================================================
  497. void ShowScreen(void)
  498. {
  499.  
  500. memmove(Video,Buffer,51200);
  501.  
  502. }
  503.  
  504. //=============================================================================
  505. //
  506. //=============================================================================
  507. void ShowBackDrop(void)
  508. {
  509.  
  510. memmove(Video,BackDrop,64000);
  511.  
  512. }
  513.  
  514.  
  515.  
  516. //=============================================================================
  517. //
  518. //=============================================================================
  519. void DrawSkyRange(short Angle,short column,short wt,short rows)
  520. {
  521.     UCHAR   *SkyPtr,*BufPtr;
  522.  
  523. SkyPtr = Sky + Angle;           // Get offset into Sky buffer
  524. BufPtr = Buffer + column;       // Video buffer column to start with
  525. while (rows-- > 0)
  526.     {
  527.     memmove(BufPtr,SkyPtr,wt);  // Move width from Sky to buffer
  528.     BufPtr += 320;              // Next row of Video buffer
  529.     SkyPtr += 320;              // Next row of Sky buffer
  530.     }
  531.  
  532. }
  533.  
  534. //=============================================================================
  535. //
  536. //=============================================================================
  537. void DrawView(void)
  538. {
  539.     short   column,Angle,px,py;
  540.     short   Alt1,Alt2;
  541.     unsigned short offset;
  542.  
  543.  
  544. // Draw the sky in 2 sections, first start out with the column of the sky
  545. // for our current angle and draw as much as possible, then start with column
  546. // zero of the sky and draw any remaining columns
  547.  
  548. Angle = USERA % 320;                    // Get starting column of sky buffer
  549. px = 320 - Angle;                       // Get width of sky we can draw
  550. if (px)
  551.     DrawSkyRange(Angle,0,px,150);       // Draw 150 rows of width
  552.  
  553. py = 320 - px;                          // Now get remaining width we need
  554. if (py)
  555.     DrawSkyRange(0,px,py,150);          // And draw from column 0 of sky
  556.  
  557. Angle = USERA + 160;                    // Angle plus half the screen
  558. if (Angle >= MAX_ANGLE)                 // Check if beyond max angle range
  559.     Angle -= MAX_ANGLE;                 // and bring back down into range
  560.  
  561. px = USERX + ((cosine[Angle] * 6) >> 14);
  562. py = USERY + ((sine[Angle] * 6) >> 14);
  563. offset = (py * WORLDX) + px;
  564. Alt1 = World[offset];                   // Get the height alittle in front
  565.  
  566.  
  567. offset = (USERY * WORLDX) + USERX;      // Get the offset into our world
  568. px = World[offset];                     // Get the altitude of the viewer
  569.  
  570. if (px > CurrentAlt)                    // Are we higher than our viewer height?
  571.     UserAlt = px + CurrentAlt;          // Yes, set to new height
  572. else
  573.     UserAlt = CurrentAlt;               // Otherwise stay at viewer height
  574.  
  575. if (Alt1 > UserAlt)                     // Is height in front of us higher?
  576.     UserAlt = Alt1 + CurrentAlt;        // Yes, set to new height
  577.  
  578. CurrentAngle = USERA;                   // Start with left side of screen
  579.  
  580. for (CurrentColumn = 0; CurrentColumn < 320; CurrentColumn += COLUMN_AMOUNT)
  581.     {
  582.     DrawLine();                         // Draw current vertical column
  583.     CurrentAngle += COLUMN_AMOUNT;      // Next Angle on the screen
  584.     if (CurrentAngle >= MAX_ANGLE)      // Check if we wrapped around
  585.         CurrentAngle -= MAX_ANGLE;
  586.     }
  587.  
  588. ShowScreen();                           // Copy buffer to screen
  589.  
  590. }
  591.  
  592. //=============================================================================
  593. //
  594. //=============================================================================
  595. void DrawScreen(void)
  596. {
  597.     short   done,Angle,i;
  598.     short   SpinAngle;
  599.  
  600. memset(Buffer,0,64000);
  601. done = 0;
  602. SpinAngle = MAX_ANGLE >> 5;
  603.  
  604. while (!done)
  605.     {
  606.     DrawView();
  607.  
  608.     if (Keys[ESCAPE_KEY])
  609.         break;
  610.  
  611.     if (Keys[UP_ARROW_KEY])
  612.         {
  613.         Angle = USERA + HALF_SCREEN;
  614.         if (Angle >= MAX_ANGLE) Angle -= MAX_ANGLE;
  615.  
  616.         USERX = USERX + ((cosine[Angle] * VIEWER_SPEED) >> 14);
  617.         USERY = USERY + ((sine[Angle] * VIEWER_SPEED) >> 14);
  618.         USERX = USERX % WORLDX;
  619.         USERY = USERY % WORLDY;
  620.         }
  621.  
  622.     if (Keys[DOWN_ARROW_KEY])
  623.         {
  624.         Angle = USERA + HALF_SCREEN + (MAX_ANGLE/2);
  625.         if (Angle >= MAX_ANGLE) Angle -= MAX_ANGLE;
  626.  
  627.         USERX = USERX + ((cosine[Angle] * VIEWER_SPEED) >> 14);
  628.         USERY = USERY + ((sine[Angle] * VIEWER_SPEED) >> 14);
  629.         USERX %= WORLDX;
  630.         USERY %= WORLDY;
  631.         }
  632.  
  633.     if (Keys[LEFT_ARROW_KEY])
  634.         {
  635.         USERA = USERA - SpinAngle;
  636.         if (USERA < 0) USERA += MAX_ANGLE;
  637.         }
  638.  
  639.     if (Keys[RIGHT_ARROW_KEY])
  640.         {
  641.         USERA = USERA + SpinAngle;
  642.         if (USERA >= MAX_ANGLE) USERA -= MAX_ANGLE;
  643.         }
  644.  
  645.     if (Keys[PGUP_KEY])
  646.         {
  647.         if (HorizonTilt > 4)
  648.             {
  649.             HorizonTilt--;
  650.             for (i = 0; i < (RAYLENGTH+50); i++)
  651.                 startpostable[i] = startposOrg[i] + HorizonTilt;
  652.  
  653.             }
  654.         }
  655.  
  656.     if (Keys[PGDN_KEY])
  657.         {
  658.         if (HorizonTilt < 90)
  659.             {
  660.             HorizonTilt++;
  661.             for (i = 0; i < (RAYLENGTH+50); i++)
  662.                 startpostable[i] = startposOrg[i] + HorizonTilt;
  663.             }
  664.         }
  665.  
  666.     if (Keys[MINUS_KEY])
  667.         {
  668.         if (CurrentAlt > 8)
  669.             CurrentAlt--;
  670.  
  671.         }
  672.  
  673.     if (Keys[PLUS_KEY])
  674.         {
  675.         if (CurrentAlt < 100)
  676.             CurrentAlt++;
  677.         }
  678.  
  679.     }
  680.  
  681. }
  682.  
  683. //=============================================================================
  684. //
  685. //=============================================================================
  686. void main(short argc,char **argv)
  687. {
  688.     short   result;
  689.  
  690. HorizonTilt = 80;                       // Initialize our Horizon
  691. CurrentAlt = USERALT;                   // And default altitude
  692. InitSinCos();                           // Build our trig tables
  693. InitStartPosTable();                    // and Height to Row tables
  694. result = LoadFiles();                   // Load the pictures
  695. if (result)
  696.     {
  697.     printf("Error: %d while loading pictures.\n",result);
  698.     return;
  699.     }
  700.  
  701. Buffer = malloc(64000);                 // Init the buffer we'll draw to
  702. if (Buffer == NULL)
  703.     {
  704.     printf("Not enough memory.\n");
  705.     return;
  706.     }
  707.  
  708. USERX=160;                              // Starting X,Y coordinates
  709. USERY=100;
  710. USERA=960;                              // Starting angle.
  711.  
  712. Video = (UCHAR *)0xA0000;               // Address of VGA screen
  713. oldvec=_dos_getvect(KEYBD);             // Get the current keyboard vector
  714. _dos_setvect(KEYBD,myInt);              // And replace it with ours
  715.  
  716. SetVideoMode(0x13);                     // Switch to 320x200 256 color mode
  717. SetPalette((UCHAR *)PalBuf);            // And set our palette
  718. ShowBackDrop();                         // Show the main screen image
  719. DrawScreen();                           // Show terrain and allow moving
  720.  
  721. SetVideoMode(0x03);                     // Back to text color 80 mode
  722.  
  723. _dos_setvect(KEYBD,oldvec);             // Put back the old keyboard vector
  724.  
  725. }
  726.  
  727.  
  728.